﻿#include <iostream>
#include <array>
#include <vector>
#include <fstream>
#include <functional>
#include <map>
#include <ctime>
#include "des/des.hpp"
#include "des/desDataEncryption.hpp"

using namespace des;


void testString() {

	des::DES<des::DESRule_demo> d(135792468);

	std::cout << "=======================数字加密测试========================" << std::endl;

	int64 a = 123456789;

	std::cout << "原数字: " << a << std::endl;
	int64 ae = d.encryptBlock(a);
	std::cout << "加密后数字：" << ae << std::endl;
	std::cout << "解密后数字：" << d.decryptBlock(ae) << std::endl;


	std::cout << "=======================ANCII字符串加密测试========================" << std::endl;

	int8 constexpr strLen = 41;
	char str1[strLen] = "1234567890123456789012345678901234567890";
	char* e;

	std::cout << "原字符串: " << str1 << std::endl;
	e = d.encrypt(str1, str1 + strLen);
	std::cout << "加密后字符串：" << e << std::endl;

	// 注意，由于编码后尾部补足了64位，所以要对补足后的那么多位解码
	int8 constexpr eLen = (strLen % (8 / sizeof(char)) == 0) ?
		(strLen) :
		((strLen / (8 / sizeof(char)) + 1) * (8 / sizeof(char)));
	e = d.decrypt(e, e + eLen);
	std::cout << "解密后字符串：" << e << std::endl;
}


void testFile() {

	int64 key = 0;
	std::cout << "请输入密钥: ";
	std::cin >> key;

	des::DES<des::DESRule_demo> d(key);
	// op map  1: 加密  2: 解密
	std::unordered_map<int, std::function<int(std::string const&)>> opMap{
		{1, [&d](std::string const& f)->int { return d.encrypt(f); }},
		{2, [&d](std::string const& f)->int { return d.decrypt(f); }}
	};
	std::string fileName;
	
	while (1) {
		int n;
		std::cout << "请输入需要测试的模式 (1)加密 (2)解密 (0)退出：";
		std::cin >> n;

		if (n == 0) break;
		if (opMap.find(n) == opMap.end()) continue;

		std::cout << "请输入需要操作的文件名: ";
		std::cin >> fileName;

		auto bclock = clock();
		int res = opMap[n](fileName);

		if (res) std::cout << "文件名错误！" << std::endl;
		else std::cout << "操作成功！用时: " << (clock() - bclock) * 1. / CLOCKS_PER_SEC << "秒" << std::endl;
	}
}


int main() {

	testFile();
	//testString();

	auto constexpr keys = des::key::keyGenerate<des::DESRule_demo>(123456789);

	return 0;
}

